<?php


namespace app\cms\community\lib;


use app\cms\community\lib\Query\ElasticsearchQuery;
use app\cms\community\lib\saas\saasAccount;
use iflow\exception\Adapter\HttpException;
use iflow\Response;
use think\facade\Db;

class QueryModel extends ElasticsearchQuery {

    // 验证是否为saas基础模型
    const isSaasModel = false;

    /**
     * 初始化链接数据
     * QueryModel constructor.
     * @param array $data
     * @throws \Exception
     */
    public function __construct(array $data = [])
    {
        // 初始化数据库配置
        $config = config('database');
        $saasEnable = config('app@saasEnable');

        // 获取当前连接数据
        if (!static::isSaasModel && $saasEnable && empty($config['connections']['saas'])) {
            $info = app(saasAccount::class) -> getSaasAccount();
            if (empty($info['db_ip']) || empty($info['db_port'])) throw new HttpException(403, '当前数据服务不可用');
            $config['connections']['saas'] = $config['connections']['mysql'];
            $config['connections']['saas'] = array_merge($config['connections']['saas'], [
                // 服务器地址
                'hostname' => $info['db_ip'],
                // 数据库名
                'database' => $info['db_name'],
                // 用户名
                'username' => $info['db_user'],
                // 密码
                'password' => $info['db_password'],
                // 端口
                'hostport' => $info['db_port']
            ]);
            Db::setConfig($config);
        }
        if (!static::isSaasModel && $saasEnable) $this->connection = 'saas';

        $this->initialization();
        parent::__construct($data);
    }

    // 子类初始化
    public function initialization() {}

    /**
     * 分页查询
     * @param $query | Model 查询对象
     * @return Response
     */
    public function paginateQuery($query): Response
    {
        $query = $query -> paginate([
            'page' => request() -> getParams('page'),
            'list_rows' => request() -> getParams('rows') ?: 10
        ]);
        $items = $query -> items();
        return $items ?
            message() -> success('查询成功', $items, [
                'count' => $query -> total(),
                'current' => $query -> lastPage()
            ]): message() -> nodata('暂无数据');
    }

    /**
     * 删除数据
     * @param array $where
     * @return Response
     */
    public function deleteData(array $where): Response
    {
        $delete = $this-> where($where) -> delete();
        return $delete ? message() -> success('删除成功') :
            message() -> update_failed('删除失败');
    }

    /**
     * 创建数据
     * @param array $data
     * @param callable|null $callback
     * @return Response
     */
    public function createData(array $data, ?callable $callback = null): Response
    {
        try {
            $this->startTrans();
            $info = self::create($data) -> toArray();
            if ($callback !== null) call_user_func($callback, $info);
            $this->commit();
            return message() -> success('创建成功', $info);
        } catch (\Throwable $exception) {
            $this->rollback();
            return message() -> update_failed('创建失败, 请重试: '. $exception -> getMessage());
        }
    }

    /**
     * 更新数据
     * @param array $data
     * @param array $where
     * @return Response
     */
    public function updateInfo(array $data, array $where = []): Response
    {
        $info = self::update($data, $where) -> toArray();
        return $info
            ? message() -> success('更新成功', $info)
            : message() -> update_failed('更新失败');
    }

    /**
     * 查询单条数据
     * @param array $where
     * @param array $fields
     * @return array
     */
    public function findInfo(array $where = [], array $fields = []): array
    {
        $info = $this->where($where);
        if ($fields) $info -> field($fields);
        $info = $info -> findOrEmpty();
        return $info -> isEmpty() ? [] : $info -> toArray();
    }

    /**
     * 执行原生sql语句
     * @param string $sql
     * @param array $bind
     * @return mixed
     */
    public function execute(string $sql, array $bind = []): mixed
    {
        return Db::connect($this->getConnection()) -> execute($sql, $bind);
    }

    /**
     * 执行原生sql查询语句
     * @param string $sql
     * @param array $bind
     * @param bool $master
     * @return mixed
     */
    public function query(string $sql, array $bind = [], bool $master = false): mixed {
        return Db::connect($this->getConnection()) -> query($sql, $bind, $master);
    }

    /**
     * 更新或新增
     * @param array $data
     * @param string $pk
     * @return Response
     */
    public function saveOrUpdate(array $data, string $pk = ''): Response {
        $this->pk($pk ?: $this -> pk);
        try {
            $save = $this->saveAll($data);
            return message() -> success('保存成功', $save -> toArray());
        } catch (\Exception $e) {
            return message() -> update_failed($e -> getMessage());
        }
    }
}